#!/usr/bin/env python2
#-*- coding: utf-8 -*-

"""
Created on 20160328
"""

import re
import web
import json
import sys
import hashlib
import traceback

from Umpweb.common import log
from Umpweb.common import config
from Umpweb.common import utils
from Umpweb.common.utils import login_required
from Umpweb.base import session, _, render_jinja
from Umpweb.db import api as db_api


LOG = log.get_log('Umpweb.index')


render = render_jinja('static/templates/', encoding='utf-8')


def write_stor_session(username, user=None, user_id=None, token=None):
    if not user_id:
        user = user or db_api.user_get_with_name(username)
        if not user :
            raise Exception('not found user %s ' % (username))
        user_id = user.id
        
    #
    session.user.name = username
    session.user.id = user_id
    session.user.token = token
    session.user.is_login = 1 

    return session


def reply_result(reply):
    result = json.loads(reply.get('result'))
    api_name = result.keys()[0]
    return result.get(api_name)


def reply_error(reply):
    return reply_result(reply).get('error', '')


def reply_success(reply):
    return reply_result(reply).get('success', False)
    

def reply_inventory(reply):
    return reply_result(reply).get('inventory', {})


def reply_validSession(reply):
    return reply_result(reply).get('validSession', False)


def load_reply(reply_json):
    reply = {}
    if reply_json:
        reply = json.loads(reply_json)
    return reply

        
def valid_fusionstack_sessionID(session_uuid):
    values = {
            "org.zstack.header.identity.APIValidateSessionMsg":
            {
                "sessionUuid": session_uuid
            }
    }

    reply_json = utils._execute_http(values, host='127.0.0.1', port='8080', url='/zstack/api')

    reply = load_reply(reply_json)

    if reply_success(reply):
        return reply_validSession(reply)
    else:
        return False

def fusionstack_logout(session_uuid):
    values = {
            "org.zstack.header.identity.APILogOutMsg":
            {
                "sessionUuid": session_uuid
            }
    }
    if not session_uuid:
        return 

    reply_json = utils._execute_http(values, host='127.0.0.1', port='8080', url='/zstack/api')

    reply = load_reply(reply_json)
    print reply

    if reply_success(reply):
        return reply_validSession(reply)
    else:
        return False



class LoginBase(object):

    def _login_action(self, username, password, valid_password=True):
        values = {'username':username, 'password':password}
        if not valid_password:
            values['without_password'] = True

        body = {'Login':{'params':values}}

        reply = web.config._server.api_sync_call(body)
        reply = json.loads(reply)

        return reply

    def generate_fusionstor_user(self, username, password):
        user = db_api.user_get_with_name(username)
        if user:
            return None, user

        values = {
                'name': username, 
                'protection_domain_ids': u'', 
                'quota': u'', 
                'repnum': u'2', 
                'chap_password': u'000000000000', 
                'password': password,
                'identity': u'tenancy', 
                'chap_name': u'test'
        }

        body = {'UserCreateForce':{'params':values}}

        reply = json.loads(utils.web_return(body))
        if not reply.get('reply', {}).get('is_success', False):
            tip = reply.get('reply', {}).get('error','')
            return render.login(tip=tip), None


    def _set_fusionstor_login(self, username, password):
        result, user = self.generate_fusionstor_user(username, password)
        if result:
            return result

        #Login FusionStor and Get Token
        stor_reply = self._login_action(username, password, valid_password=False)
        if self.stor_reply_success(stor_reply):
            token = self.get_fusionstor_token(stor_reply)
        
            session = write_stor_session(username, user=user, token=token)
        else:
            error = self.stor_reply_error(stor_reply)
            return render.login(tip=error)

    def get_fusionstor_token(self, reply):
        records = reply.get('records', {})
        return records.get('token') 

    def stor_reply_success(self, reply):
        return reply.get('reply', {}).get('is_success', False)

    def stor_reply_error(self, reply):
        return reply.get('reply', {})['error']


class Login(LoginBase):

    def GET(self):
        x = web.input()
        tip = x.get('tip')
        if tip is None:
            tip = ''
        return  render.login(tip=tip)

    def POST(self):
        x = web.input()
        username = x.username.strip()
        password = x.password.strip()

        if config.is_fusionstack_sso:
            try:
                return self.fusionstack_login(username, password)
            except Exception, e:
                error = str(e)
                return render.login(tip=error)
        else:
            return self.fusionstor_login(username, password)

    def fusionstor_login(self, username, password):
        try:
            reply = self._login_action(username, password)
        except Exception,e:
            LOG.info('%s' % (e))
            return render.login(tip="%s"%e)

        if self.stor_reply_success(reply):

            token = self.get_fusionstor_token(reply)

            write_stor_session(username, token=token)

            return web.seeother('/home')
        else:
            tip = reply.get('reply', {}).get('error','')
            return render.login(tip=tip)

    def fusionstack_login(self, username, password):
        values = {
                "org.zstack.header.identity.APILogInByAccountMsg": 
                {
                    "password": hashlib.sha512(password).hexdigest(),
                    "accountName": username
                }
        }

        reply_json = utils._execute_http(values, host='127.0.0.1', port='8080', url='/zstack/api')

        print "FusionStack Login:", reply_json
        reply = load_reply(reply_json)

        if reply_success(reply):
            #Set FusionStor Cookie and Session
            self._set_fusionstor_login(username, password)

            #Cache FusionStack Cookie Info
            inventory = reply_inventory(reply)
            session.user.fusionstack_sessionId = inventory.get('uuid')
            session.user.accountUuid = inventory.get('accountUuid')

            return web.seeother('/home')
        else:
            tip = reply_error(reply) 
            return render.login(tip=tip)


class Logout:
    def GET(self):
        x = web.input()
        print x 
        sessionUuid = x.get("sessionUuid")
        username = session.user
        session.kill()
        oplog_values = {
            'operation':u'退出用户',
            'oplog_obj':username.name,
            'resource': "用户",
            'status':'成功',
        }
        db_api.oplog_create(oplog_values)

        http_host = web.ctx.env.get('HTTP_HOST', '')
        http_host = http_host.split(':')[0]

        if config.is_fusionstack_sso:
            try:
                fusionstack_logout(sessionUuid)
            except Exception, e:
                print "Logout Fusionstack ERROR:", e
                pass
            return '<script type="text/javascript">window.location.href="http://%s";</script>' % (http_host)
        else:
            return web.seeother('/login')  

class IsLogin:

    def GET(self):
        x = web.input()
        fusionstack_sessionId = x.get('fusionstack_sessioinId')
        account_name = x.get('account_name')
        session = web.config._session
        
        web.header("Content-Type", "plain/text")
        if fusionstack_sessionId and valid_fusionstack_sessionID(fusionstack_sessionId):
            write_stor_session(account_name)
            return 'True'
        else:
            is_login = 'True'
            if 'user' in session.keys() and session.user.get('is_login') == 0:
                is_login = 'False'
        return is_login

class Cookies:
    
    def GET(self):
        return render.cookies()

class Home:
    
    @login_required
    def GET(self, uuid=1):
        username = web.config._session.user.name 
        user = db_api.user_get_with_name(username)
        if not user:
            web.ctx.session.kill()
            return web.seeother('/login')                                                                                                                                             
        roles = db_api.role_get_with_user(user.id)
        role_id = roles[0].id
        role = db_api.role_get(role_id)
        clusters = db_api.cluster_get_all()
        reload(config)
        expired_time = config.expired_time
        is_showPool = config.is_showPool
        is_fusionstack_sso = config.is_fusionstack_sso
        print is_fusionstack_sso
        return render.home(user=user, 
                        is_fusionstack_sso=is_fusionstack_sso,
                        session=session, clusters=clusters, role=role,\
                        expired_time=expired_time, is_showPool=is_showPool)

class Favicon:
    def GET(self):
        return web.seeother('/static/favicon.ico')

class SwitchLanguage:

    def POST(self):
        web.header("Content-Type", "text/plain")
        x = web.input()
        lang = x.get('lang', 'zh_CN')
        session.user.lang = lang
        return 'SUCC'

class SessionTimeout:

    def GET(self):
        params = web.input()
        web.header("Content-Type", "plain/text")
        try:
            username = web.config._session.user
            if not username :
                username = params.get("username")
            web.ctx.session.kill()
            oplog_values = {'operation': u'退出用户',
                            'oplog_obj': username.name,
                            'resource': "用户",
                            'status': u'成功',
                            'detail': u'用户无操作,超时退出'}
            db_api.oplog_create(oplog_values)
        except Exception,e:
            return '%s'%e
        return "SUCC"


class ValidLogin:
        
    def GET(self):
        return render.cookies()

class ValidSessionUuid(LoginBase):

    def POST(self):
        x = web.input()
        sessionUuid = x.get('sessionUuid')
        accountName = x.get('accountName')
        accountUuid = x.get('accountUuid')


        web.header("Content-Type", "application/json")

        is_login = False
        if sessionUuid:
            is_login = valid_fusionstack_sessionID(sessionUuid)
            fusionstor_is_login = web.config._session.user.is_login
            if not fusionstor_is_login:
                self._set_fusionstor_login(accountName, 'admin')

                session.user.fusionstack_sessionId = sessionUuid
                session.user.accountUuid =  x.get('accountUuid')
        print "ValidSessionUuid %s:" % (sessionUuid), is_login

        return json.dumps({'is_login':is_login})
